home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir24 / psi110g.zip / SCC.C < prev    next >
C/C++ Source or Header  |  1994-04-17  |  57KB  |  1,537 lines

  1. /* Generic driver for Z8530 boards, modified from the PE1CHL
  2.  * driver for use with NOS. This version also supports the NRS
  3.  * mode when used as an asynch port. Device setup is similar to
  4.  * that of the PE1CHL version, with the addition of user specification
  5.  * of buffer size (bufsize). See the file "scc.txt" for general
  6.  * information on the use of this driver and setup procedures.
  7.  *
  8.  * General differences between this driver and the original version:
  9.  *
  10.  * 1) Slip encoding and decoding is not done in the driver, but
  11.  *    using the routines in slip.c, and these routines are supported
  12.  *    in a manner similar to the asynch routines for the 8250. The
  13.  *    input is handled via fifo buffer, while output is direct. The
  14.  *    routines scc_send and get_scc are called via pointers in the
  15.  *    Slip and Nrs structs for the parcticular channel.
  16.  *
  17.  * 2) The timer routine, scctim, is not installed directly in the
  18.  *    timer interrupt chain, but is called through the systick routine
  19.  *    in pc.c.
  20.  *
  21.  * 3) Facilities of nos are used whenever possible in place of direct
  22.  *    structure or variable manipulation. Mbuf management is handled
  23.  *    this way, along with interface initialization.
  24.  *
  25.  * 4) Nrs mode support is added in a manner similar to that of the
  26.  *    Slip support. I have not had an opportunity to test this, but
  27.  *    it is essentially identical to the way the 8250 version works.
  28.  *
  29.  * 5) Callsign specification on radio modes (kiss,nrs,ax25) is an
  30.  *    option. If not supplied, the value of Mycall will be used.
  31.  *
  32.  * 6) Bufsize specification is now a parameter on setup of each channel.
  33.  *    This is the size of the fifo on asynch input, and the size of
  34.  *    mbuf buffers for sdlc mode. Since the fifo buffer can fill up,
  35.  *    this value should be reasonably large for asynch mode. Mbufs
  36.  *    are chained when they fill up, so having a small bufsize with
  37.  *    sdlc modes (ax25) does not result in loss of characters.
  38.  *
  39.  * 7) Because slip and nrs decoding is handled outside the driver,
  40.  *    sccstat cannot be used to report sent and receive packet counts
  41.  *    in asynch mode, and these fields are blanked on display in asynch
  42.  *    modes.
  43.  *
  44.  *
  45.  * I am interested in setting up some default initializations for
  46.  * the popular Z8530 boards, to minimize user problems in constructing
  47.  * the proper attach init entries. These would allow for shortened
  48.  * entries to use the defaults, such as "attach scc 1 init drsi" to
  49.  * attach a DRSI board in standard configuration at its default address.
  50.  * Since I do not have complete technical information on all such boards,
  51.  * I would very much appreciate any information that users can provide
  52.  * me regarding particular boards.
  53.  *
  54.  * 1/25/90
  55.  *
  56.  * Modifications:
  57.  *
  58.  * 2/17/90:
  59.  *
  60.  * 1) Added mods from PE1CHL which reflect relevent changes to the
  61.  *    scc driver in his version of net between 10/89 and 1/90. Changes
  62.  *    incorporated include additional delays in sccvec.asm, addition
  63.  *    of external clock mode, and initialization for the 8536 as a
  64.  *    clock divider on the DRSI board. "INLINE" is a slight delay
  65.  *    for register access incorporated for use with the inline i/o
  66.  *    code in MSC. This may not be useful or necessary with TURBO.
  67.  *    Changes making "TPS" a variable were not added, since the
  68.  *    scc timer does not install itself on the hardware interrupt
  69.  *    in this version.
  70.  *
  71.  *
  72.  * Ken Mitchum, KY3B       km@cs.pitt.edu  km@dsl.pitt.edu
  73.  *                             or mail to the tcpip group
  74.  * 5/07/92:
  75.  *
  76.  * 1) Changes needed for BayCom-USCC card were made. CTS-Interrupt
  77.  *    was disabled, because it keeps the system hanging. Clock sources
  78.  *    will be changed when transmitter is switched on/off, if internal
  79.  *    clock is used. Now DF9ICs G3RUH compatible modem is supported,
  80.  *    which needs NRZ-signals and provides external clocks.
  81.  *
  82.  * Rene Stange, DG0FT @DB0KG.DEU.EU
  83.  *
  84.  */
  85.   
  86. /* Added ANSI-style prototypes, reformatted source, minor delinting.
  87.  * Integrated into standard 900201 NOS by KA9Q.
  88.  */
  89.   
  90. /*
  91.  * Generic driver for Z8530 SCC chip in SLIP, KISS or AX.25 mode.
  92.  *
  93.  * Written by R.E. Janssen (PE1CHL) using material from earlier
  94.  * EAGLE and PC100 drivers in this package.
  95.  *
  96.  * The driver has initially been written for my own Atari SCC interface
  97.  * board, but it could eventually replace the other SCC drivers.
  98.  *
  99.  * Unfortunately, there is little consistency between the different interface
  100.  * boards, as to the use of a clock source, the solution for the fullduplex
  101.  * clocking problem, and most important of all: the generation of the INTACK
  102.  * signal.  Most designs do not even support the generation of an INTACK and
  103.  * the read of the interrupt vector provided by the chip.
  104.  * This results in lots of configuration parameters, and a fuzzy
  105.  * polltable to be able to support multiple chips connected at one interrupt
  106.  * line...
  107.  *
  108.  */
  109.   
  110. #include <ctype.h>
  111. #include <time.h>
  112. #include <dos.h>
  113. #include "global.h"
  114. #ifdef SCC
  115. #include "mbuf.h"
  116. #include "config.h"
  117. #include "netuser.h"
  118. #include "proc.h"
  119. #include "iface.h"
  120. #include "pktdrvr.h"
  121. #include "slip.h"
  122. #include "nrs.h"
  123. #include "i8250.h"
  124. #include "scc.h"
  125. #include "z8530.h"
  126. #include "z8536.h"
  127. #include "ax25.h"
  128. #include "trace.h"
  129. #include "pc.h"
  130. #include "kiss.h"
  131. #include "devparam.h"
  132.   
  133. /* interrupt handlers */
  134. extern INTERRUPT sccvec();
  135. extern INTERRUPT sccnovec();
  136.   
  137. /* variables used by the SCC interrupt handler in sccvec.asm */
  138. static INTERRUPT (*Orgivec)();  /* original interrupt vector */
  139.   
  140. struct sccinfo Sccinfo = {0};       /* global info about SCCs */
  141. struct sccchan *Sccchan[2 * MAXSCC] = {0}; /* information per channel */
  142. ioaddr Sccvecloc = {0};         /* location to access for SCC vector */
  143. unsigned char Sccmaxvec = {0};      /* maximum legal vector from SCC */
  144. ioaddr Sccpolltab[MAXSCC+1][2] = {0};   /* polling table when no vectoring */
  145.   
  146. #if defined(INLINE)
  147. static unsigned scc_delay __ARGS((unsigned v));
  148.   
  149. static unsigned scc_delay (v)       /* delay for about 5 PCLK cycles */
  150. unsigned v;              /* pass-through used for input */
  151.   
  152. {
  153.     register int i,j;            /* it takes time to save them */
  154.   
  155.     return v;                /* return the passed parameter */
  156. }
  157. #endif
  158.   
  159. unsigned char Random = 0;       /* random number for p-persist */
  160.   
  161. static int scc_call __ARGS((struct iface *ifp,char *call));
  162. static int scc_init __ARGS((int nchips,ioaddr iobase,int space,int aoff,
  163. int boff,int doff,ioaddr intack,int ivec,long clk,int pclk,int hwtype,
  164. int hwparam));
  165. static int scc_raw __ARGS((struct iface *ifp,struct mbuf *bp));
  166. static int scc_stop __ARGS((struct iface *ifp));
  167. static int get_scc __ARGS((int dev));
  168. static int scc_send __ARGS((int dev,struct mbuf *bp));
  169. static int scc_async __ARGS((struct sccchan *scc));
  170.   
  171. static void scc_sdlc __ARGS((struct sccchan *scc));
  172. static void scc_tossb __ARGS((struct sccchan *scc));
  173. static void scc_txon __ARGS((struct sccchan *scc));
  174. static void scc_txoff __ARGS((struct sccchan *scc));
  175. static int32 scc_aioctl __ARGS((struct iface *ifp,int cmd,int set,int32 val));
  176. static int32 scc_sioctl __ARGS((struct iface *ifp,int cmd,int set,int32 val));
  177. static void scc_sstart __ARGS((struct sccchan *scc));
  178. static unsigned int scc_speed __ARGS((struct sccchan *scc,
  179. unsigned int clkmode,long speed));
  180. static void scc_asytx __ARGS((struct sccchan *scc));
  181. static void scc_asyex __ARGS((struct sccchan *scc));
  182. static void scc_asyrx __ARGS((struct sccchan *scc));
  183. static void scc_asysp __ARGS((struct sccchan *scc));
  184. static void scc_sdlctx __ARGS((struct sccchan *scc));
  185. static void scc_sdlcex __ARGS((struct sccchan *scc));
  186. static void scc_sdlcrx __ARGS((struct sccchan *scc));
  187. static void scc_sdlcsp __ARGS((struct sccchan *scc));
  188.   
  189. /* Attach an SCC channel to the system, or initialize SCC driver.
  190.  * operation depends on argv[2]:
  191.  * when "init", the SCC driver is initialized, and global information about
  192.  * the hardware is set up.
  193.  * argv[0]: hardware type, must be "scc"
  194.  * argv[1]: number of SCC chips we will support
  195.  * argv[2]: mode, must be: "init" in this case
  196.  * argv[3]: base address of SCC chip #0 (hex)
  197.  * argv[4]: spacing between SCC chip base addresses
  198.  * argv[5]: offset from chip base address to channel A control register
  199.  * argv[6]: offset from chip base address to channel B control register
  200.  * argv[7]: offset from each channel's control register to data register
  201.  * argv[8]: address of INTACK/Read Vector port. 0 to read from RR3A/RR2B
  202.  * argv[9]: CPU interrupt vector number for all connected SCCs
  203.  * argv[10]: clock frequency (PCLK/RTxC) of all SCCs in cycles per second
  204.  *       prefix with "p" for PCLK, "r" for RTxC clock (for baudrate gen)
  205.  * argv[11]: optional hardware type (for special features)
  206.  * argv[12]: optional extra parameter for special hardware
  207.  *
  208.  * otherwise, a single channel is attached using the specified parameters:
  209.  * argv[0]: hardware type, must be "scc"
  210.  * argv[1]: SCC channel number to attach, 0/1 for first chip A/B, 2/3 for 2nd...
  211.  * argv[2]: mode, can be:
  212.  *      "slip", "kiss", "ax25"
  213.  * argv[3]: interface label, e.g., "sl0"
  214.  * argv[4]: maximum transmission unit, bytes
  215.  * argv[5]: interface speed, e.g, "1200". prefix with "d" when an external
  216.  *      divider is available to generate the TX clock.  When the clock
  217.  *      source is PCLK, this can be a /32 divider between TRxC and RTxC.
  218.  *      When the clock is at RTxC, the TX rate must be supplied at TRxC.
  219.  *      This is needed only for AX.25 fullduplex.
  220.  *      When this arg is given as "ext", the transmit and receive clock
  221.  *      are external, and the BRG and DPLL are not used.
  222.  *      On the BayCom-USCC card "ext" enables NRZ-mode for DF9IC-modem.
  223.  * argv[6]: buffer size
  224.  * argv[7]: callsign used on the radio channels (optional)
  225.  */
  226.   
  227. int
  228. scc_attach(argc,argv)
  229. int argc;
  230. char *argv[];
  231. {
  232.     register struct iface *ifp;
  233.     struct sccchan *scc;
  234.     unsigned int chan,brgrate;
  235.     int pclk = 0,hwtype = 0,hwparam = 0;
  236.     int xdev;
  237.   
  238.     /* first handle the special "init" mode, to initialize global stuff */
  239.   
  240.     if(!strcmp(argv[2],"init")){
  241.         if(argc < 11)           /* need at least argv[1]..argv[10] */
  242.             return -1;
  243.   
  244.         if(isupper(argv[10][0]))
  245.             argv[10][0] = tolower(argv[10][0]);
  246.   
  247.         if(argv[10][0] == 'p'){ /* wants to use PCLK as clock? */
  248.             pclk = 1;
  249.             argv[10]++;
  250.         } else {
  251.             if(argv[10][0] == 'r')  /* wants to use RTxC? */
  252.                 argv[10]++;     /* that's the default */
  253.         }
  254.         if(argc > 11)           /* optional hardware type */
  255.             hwtype = htoi(argv[11]);    /* it is given in hex */
  256.   
  257.         if(argc > 12)           /* optional hardware param */
  258.             hwparam = htoi(argv[12]);   /* also in hex */
  259.   
  260.         return scc_init(atoi(argv[1]),(ioaddr) htol(argv[3]),atoi(argv[4]),
  261.         atoi(argv[5]),atoi(argv[6]),atoi(argv[7]),
  262.         (ioaddr) htol(argv[8]),atoi(argv[9]),
  263.         atol(argv[10]),pclk,hwtype,hwparam);
  264.     }
  265.   
  266.     /* Check for existing interface name ! - WG7J */
  267.     if(if_lookup(argv[4]) != NULLIF){
  268.         tprintf(Existingiface,argv[3]);
  269.         return -1;
  270.     }
  271.   
  272.     /* not "init", so it must be a valid mode to attach a channel */
  273.     if(strcmp(argv[2],"ax25") && strcmp(argv[2],"kiss") &&
  274.     strcmp(argv[2],"slip") && strcmp(argv[2],"nrs")){
  275.         tprintf("Mode %s unknown for SCC\n",argv[2]);
  276.         return -1;
  277.     }
  278.     if(strcmp(argv[2],"slip") == 0 || strcmp(argv[2],"kiss") == 0){
  279.         for(xdev = 0;xdev < SLIP_MAX;xdev++)
  280.             if(Slip[xdev].iface == NULLIF)
  281.                 break;
  282.         if(xdev >= SLIP_MAX){
  283.             tprintf("Too many slip devices\n");
  284.             return -1;
  285.         }
  286.     }
  287. #ifdef NRS
  288.     if(strcmp(argv[2],"nrs") == 0){
  289.         for(xdev = 0;xdev < NRS_MAX;xdev++)
  290.             if(Nrs[xdev].iface == NULLIF)
  291.                 break;
  292.   
  293.         if(xdev >= NRS_MAX){
  294.             tprintf("Too many nrs devices\n");
  295.             return -1;
  296.         }
  297.     }
  298. #endif
  299.     if(!Sccinfo.init){
  300.         tprintf("First init SCC driver\n");
  301.         return -1;
  302.     }
  303.     if((chan = atoi(argv[1])) > Sccinfo.maxchan){
  304.         tprintf("SCC channel %d out of range\n",chan);
  305.         return -1;
  306.     }
  307.     if(Sccchan[chan] != NULLCHAN){
  308.         tprintf("SCC channel %d already attached\n",chan);
  309.         return -1;
  310.     }
  311.     /* create interface structure and fill in details */
  312.     ifp = (struct iface *) callocw(1,sizeof(struct iface));
  313.     ifp->name = mallocw(strlen(argv[3]) + 1);
  314.     strcpy(ifp->name,argv[3]);
  315.   
  316.     ifp->mtu = atoi(argv[4]);
  317.     ifp->dev = chan;
  318.     ifp->stop = scc_stop;
  319.   
  320.     scc = (struct sccchan *) callocw(1,sizeof(struct sccchan));
  321.     scc->ctrl = Sccinfo.iobase + (chan / 2) * Sccinfo.space + Sccinfo.off[chan % 2];
  322.     scc->data = scc->ctrl + Sccinfo.doff;
  323.     scc->iface = ifp;
  324.   
  325.     if(isupper(argv[5][0]))
  326.         argv[5][0] = tolower(argv[5][0]);
  327.   
  328.     switch (argv[5][0]) {
  329.         case 'd':               /* fulldup divider installed? */
  330.             scc->fulldup = 1;       /* set appropriate flag */
  331.             argv[5]++;          /* skip the 'd' */
  332.             break;
  333.   
  334.         case 'e':               /* external clocking? */
  335.             scc->extclock = 1;      /* set the flag */
  336.             break;
  337.     }
  338.   
  339.     scc->bufsiz = atoi(argv[6]);
  340.     ifp->addr = Ip_addr;
  341.     Sccchan[chan] = scc;        /* put addr in table for interrupts */
  342.   
  343.     switch(argv[2][0]){             /* mode already checked above */
  344. #ifdef AX25
  345.         case 'a':   /* AX.25 */
  346.             scc_sdlc(scc);              /* init SCC in SDLC mode */
  347.   
  348.             if (!scc->extclock) {
  349.                 brgrate = scc_speed(scc,32,atol(argv[5]));/* init SCC speed */
  350.                 scc->speed = Sccinfo.clk / (64L * (brgrate + 2));/* calc real speed */
  351.             }
  352.   
  353.             brgrate = scc_speed(scc,32,atol(argv[5]));/* init SCC speed */
  354.             scc->speed = Sccinfo.clk / (64L * (brgrate + 2));/* calc real speed */
  355.             setencap(ifp,"AX25");
  356.             scc_call(ifp,argc > 7 ? argv[7] : (char *) 0);  /* set the callsign */
  357.             ifp->ioctl = scc_sioctl;
  358.             ifp->raw = scc_raw;
  359.   
  360.         /* default KISS Params */
  361.             scc->a.txdelay = 36*TPS/100;    /* 360 ms */
  362.             scc->a.persist = 25;        /* 10% persistence */
  363.             scc->a.slottime = 16*TPS/100; /* 160 ms */
  364. #if TPS > 67
  365.             scc->a.tailtime = 3*TPS/100;    /* 30 ms */
  366. #else
  367.             scc->a.tailtime = 2;        /* minimal reasonable value */
  368. #endif
  369.             scc->a.fulldup = 0;     /* CSMA */
  370.             scc->a.waittime = 50*TPS/100; /* 500 ms */
  371.             scc->a.maxkeyup = 7;        /* 7 s */
  372.             scc->a.mintime = 3;     /* 3 s */
  373.             scc->a.idletime = 120;  /* 120 s */
  374.             break;
  375.         case 'k':   /* kiss */
  376.             scc_async(scc);             /* init SCC in async mode */
  377.             brgrate = scc_speed(scc,16,atol(argv[5]));
  378.             scc->speed = Sccinfo.clk / (32L * (brgrate + 2));
  379.   
  380.             setencap(ifp,"AX25");
  381.             scc_call(ifp,argc > 7 ? argv[7] : (char *) 0);  /* set the callsign */
  382.   
  383.             ifp->ioctl = kiss_ioctl;
  384.             ifp->raw = kiss_raw;
  385.   
  386.             for(xdev = 0;xdev < SLIP_MAX;xdev++){
  387.                 if(Slip[xdev].iface == NULLIF)
  388.                     break;
  389.             }
  390.             ifp->xdev = xdev;
  391.             Slip[xdev].iface = ifp;
  392.             Slip[xdev].type = CL_KISS;
  393.             Slip[xdev].send = scc_send;
  394.             Slip[xdev].get = get_scc;
  395.             ifp->rxproc = newproc("ascc rx",256,asy_rx,xdev,NULL,NULL,0);
  396.             break;
  397. #endif
  398. #ifdef SLIP
  399.         case 's':   /* slip */
  400.             scc_async(scc);             /* init SCC in async mode */
  401.             brgrate = scc_speed(scc,16,atol(argv[5]));
  402.             scc->speed = Sccinfo.clk / (32L * (brgrate + 2));
  403.             setencap(ifp,"SLIP");
  404.             ifp->ioctl = scc_aioctl;
  405.             ifp->raw = slip_raw;
  406.             for(xdev = 0;xdev < SLIP_MAX;xdev++){
  407.                 if(Slip[xdev].iface == NULLIF)
  408.                     break;
  409.             }
  410.             ifp->xdev = xdev;
  411.             Slip[xdev].iface = ifp;
  412.             Slip[xdev].type = CL_SERIAL_LINE;
  413.             Slip[xdev].send = scc_send;
  414.             Slip[xdev].get = get_scc;
  415.             ifp->rxproc = newproc("ascc rx",256,asy_rx,xdev,NULL,NULL,0);
  416.             break;
  417. #endif
  418. #ifdef NRS
  419.         case 'n':   /* nrs */
  420.             scc_async(scc);             /* init SCC in async mode */
  421.             brgrate = scc_speed(scc,16,atol(argv[5]));
  422.             scc->speed = Sccinfo.clk / (32L * (brgrate + 2));
  423.             setencap(ifp,"AX25");
  424.             scc_call(ifp,argc > 7 ? argv[7] : (char *) 0);  /* set the callsign */
  425.             ifp->ioctl = scc_aioctl;
  426.             ifp->raw = nrs_raw;
  427.   
  428.             for(xdev = 0;xdev < NRS_MAX;xdev++)
  429.                 if(Nrs[xdev].iface == NULLIF)
  430.                     break;
  431.   
  432.             ifp->xdev = xdev;
  433.             Nrs[xdev].iface = ifp;
  434.             Nrs[xdev].send = scc_send;
  435.             Nrs[xdev].get = get_scc;
  436.             ifp->rxproc = newproc("nscc rx",256,nrs_recv,xdev,NULL,NULL,0);
  437.             break;
  438. #endif
  439.     }
  440.     ifp->next = Ifaces;         /* link interface in list */
  441.     Ifaces = ifp;
  442.     return 0;
  443. }
  444.   
  445. /* SCC driver initialisation. called on "attach scc <num> init ..." */
  446. static int
  447. scc_init(nchips,iobase,space,aoff,boff,doff,intack,ivec,clk,pclk,hwtype,hwparam)
  448. int nchips;         /* number of chips */
  449. ioaddr iobase;          /* base of first chip */
  450. int space,aoff,boff,doff;
  451. ioaddr intack;          /* INTACK ioport or 0 for no INTACK */
  452. int ivec;           /* interrupt vector number */
  453. long clk;           /* clock frequency */
  454. int pclk;           /* PCLK or RTxC for clock */
  455. int hwtype;         /* selection of special hardware types */
  456. int hwparam;            /* extra parameter for special hardware */
  457. {
  458.     int chip,chan;
  459.     ioaddr chipbase;
  460.     register ioaddr ctrl;
  461.     int i_state,d;
  462.     int dum = 1;
  463.   
  464. #define z 0
  465.   
  466.     if(Sccinfo.init){
  467.         tprintf("SCC driver already initialized - nothing done\n");
  468.         return 1;
  469.     }
  470.     Sccinfo.init = 1;
  471.     Sccinfo.nchips = nchips;
  472.     Sccinfo.maxchan = (2 * nchips) - 1;
  473.     Sccinfo.iobase = iobase;
  474.     Sccinfo.space = space;
  475.     Sccinfo.off[0] = aoff;
  476.     Sccinfo.off[1] = boff;
  477.     Sccinfo.doff = doff;
  478.     Sccinfo.ivec = ivec;
  479.     Sccinfo.clk = clk;
  480.     Sccinfo.pclk = pclk;
  481.     Sccinfo.hwtype = hwtype;
  482.     Sccinfo.hwparam = hwparam;
  483.   
  484.     /* reset and pre-init all chips in the system */
  485.     for(chip = 0; chip < nchips; chip++){
  486.         chipbase = iobase + chip * space;
  487.         ctrl = chipbase + Sccinfo.off[0];
  488.         i_state = dirps();      /* because of 2-step accesses */
  489.         VOID(RDREG(ctrl));      /* make sure pointer is written */
  490.         WRSCC(ctrl,R9,FHWRES);      /* force hardware reset */
  491.         for (d = 0; d < 1000; d++)  /* wait a while to be sure */
  492.             dum *= 10;
  493.         for(chan = 0; chan < 2; chan++){
  494.             ctrl = chipbase + Sccinfo.off[chan];
  495.   
  496.             /* initialize a single channel to no-op */
  497.             VOID(RDREG(ctrl));      /* make sure pointer is written */
  498.             WRSCC(ctrl,R4,z);       /* no mode selected yet */
  499.             WRSCC(ctrl,R1,z);       /* no W/REQ operation */
  500.             WRSCC(ctrl,R2,16 * chip);   /* chip# in upper 4 bits of vector */
  501.             WRSCC(ctrl,R3,z);       /* disable rx */
  502.             WRSCC(ctrl,R5,z);       /* disable tx */
  503.             WRSCC(ctrl,R9,VIS);     /* vector includes status, MIE off */
  504.             Sccpolltab[chip][chan] = ctrl; /* store ctrl addr for polling */
  505.         }
  506.         if(hwtype & HWEAGLE)        /* this is an EAGLE card */
  507.             WRREG(chipbase + 4,0x08);   /* enable interrupt on the board */
  508.   
  509.         if(hwtype & HWPC100)        /* this is a PC100 card */
  510.             WRREG(chipbase,hwparam);    /* set the MODEM mode (22H normally) */
  511.   
  512.         if(hwtype & HWPRIMUS)       /* this is a PRIMUS-PC */
  513.             WRREG(chipbase + 4,hwparam); /* set the MODEM mode (02H normally) */
  514.   
  515.         if (hwtype & HWDRSI) {      /* this is a DRSI PC*Packet card */
  516.             ioaddr z8536 = chipbase + 7; /* point to 8536 master ctrl reg */
  517.   
  518.             /* Initialize 8536 to perform its divide-by-32 function */
  519.             /* This part copied from N6TTO DRSI-driver */
  520.   
  521.             /* Start by forcing chip into known state */
  522.   
  523.             VOID(RDREG(z8536));     /* make sure pointer is written */
  524.             WRSCC(z8536,CIO_MICR,0x01); /* force hardware reset */
  525.   
  526.             for (d = 0; d < 1000; d++)  /* wait a while to be sure */
  527.                 dum *= 10;
  528.   
  529.             WRSCC(z8536,CIO_MICR,0x00); /* Clear reset and start */
  530.   
  531.             /* Wait for chip to come ready */
  532.   
  533.             while (RDSCC(z8536,CIO_MICR) != 0x02)
  534.                 dum *= 10;
  535.   
  536.             WRSCC(z8536,CIO_MICR,0x26); /* NV|CT_VIS|RJA */
  537.             WRSCC(z8536,CIO_MCCR,0xf4); /* PBE|CT1E|CT2E|CT3E|PAE */
  538.   
  539.             WRSCC(z8536,CIO_CTMS1,0xe2);/* Continuous, EOE, ECE, Pulse output */
  540.             WRSCC(z8536,CIO_CTMS2,0xe2);/* Continuous, EOE, ECE, Pulse output */
  541.   
  542.             WRSCC(z8536,CIO_CT1MSB,0x00); /* Load time constant CTC #1 */
  543.             WRSCC(z8536,CIO_CT1LSB,0x10);
  544.             WRSCC(z8536,CIO_CT2MSB,0x00); /* Load time constant CTC #2 */
  545.             WRSCC(z8536,CIO_CT2LSB,0x10);
  546.   
  547.             WRSCC(z8536,CIO_IVR,0x06);
  548.   
  549.             /* Set port direction bits in port A and B           */
  550.             /* Data is input on bits d1 and d5, output on d0 and d4. */
  551.             /* The direction is set by 1 for input and 0 for output  */
  552.   
  553.             WRSCC(z8536,CIO_PDCA,0x22);
  554.             WRSCC(z8536,CIO_PDCB,0x22);
  555.   
  556.             WRSCC(z8536,CIO_CSR1,CIO_GCB|CIO_TCB); /* Start CTC #1 running */
  557.             WRSCC(z8536,CIO_CSR2,CIO_GCB|CIO_TCB); /* Start CTC #2 running */
  558.         }
  559.   
  560.         restore(i_state);
  561.     }
  562.     Sccpolltab[chip][0] = 0;    /* terminate the polling table */
  563.     Sccvecloc = intack;     /* location of INTACK/vector read */
  564.     Sccmaxvec = 16 * nchips;    /* upper limit on valid vector */
  565.     /* save original interrupt vector */
  566.     Orgivec = getirq(ivec);
  567.   
  568.     if(intack){ /* INTACK method selected? */
  569.         /* set interrupt vector to INTACK-generating routine  */
  570.         setirq(ivec,sccvec);
  571.     } else {
  572.         /* set interrupt vector to polling routine */
  573.         setirq(ivec,sccnovec);
  574.     }
  575.     /* enable the interrupt  */
  576.     maskon(ivec);
  577.     return 0;
  578. }
  579.   
  580. /* initialize an SCC channel in asynchronous mode */
  581. static int
  582. scc_async(scc)
  583. register struct sccchan *scc;
  584. {
  585.     int i_state;
  586.     register struct fifo *fp = &(scc->fifo);
  587.   
  588.     if((fp->buf = malloc(scc->bufsiz)) == NULLCHAR){
  589.         tprintf("scc%d: No space for rx buffer\n",scc->iface->dev);
  590.         return -1;
  591.     }
  592.     fp->bufsize = scc->bufsiz;
  593.     fp->wp = fp->rp = fp->buf;
  594.     fp->cnt = 0;
  595.   
  596.     scc->int_transmit = scc_asytx;  /* set interrupt handlers */
  597.     scc->int_extstat = scc_asyex;
  598.     scc->int_receive = scc_asyrx;
  599.     scc->int_special = scc_asysp;
  600.   
  601.     i_state = dirps();
  602.   
  603.     wr(scc,R4,X16CLK|SB1);      /* *16 clock, 1 stopbit, no parity */
  604.     wr(scc,R1,z);           /* no W/REQ operation */
  605.     wr(scc,R3,Rx8);         /* RX 8 bits/char, disabled */
  606.     wr(scc,R5,Tx8|DTR|RTS);     /* TX 8 bits/char, disabled, DTR RTS */
  607.     wr(scc,R9,VIS);         /* vector includes status */
  608.     wr(scc,R10,NRZ|z);          /* select NRZ */
  609.     wr(scc,R11,RCBR|TCBR);      /* clocks are BR generator */
  610.     wr(scc,R14,Sccinfo.pclk? BRSRC:z);  /* brg source = PCLK/RTxC */
  611.     wr(scc,R15,BRKIE);          /* enable BREAK ext/status int */
  612.   
  613.     or(scc,R3,RxENABLE);        /* enable receiver */
  614.     or(scc,R5,TxENAB);          /* enable transmitter */
  615.   
  616.     WRREG(scc->ctrl,RES_EXT_INT);   /* reset ext/status interrupts */
  617.     WRREG(scc->ctrl,RES_EXT_INT);   /* must be done twice */
  618.     scc->status = RDREG(scc->ctrl); /* read initial status */
  619.   
  620.     or(scc,R1,INT_ALL_Rx|TxINT_ENAB|EXT_INT_ENAB); /* enable interrupts */
  621.     or(scc,R9,MIE);         /* master interrupt enable */
  622.   
  623.     restore(i_state);
  624.     return 0;
  625. }
  626.   
  627. /* initialize an SCC channel in SDLC mode ; new BayCom version G8FSL */
  628. static void
  629. scc_sdlc(scc)
  630. register struct sccchan *scc;
  631. {
  632.     int i_state;
  633.   
  634.     scc->int_transmit = scc_sdlctx; /* set interrupt handlers */
  635.     scc->int_extstat = scc_sdlcex;
  636.     scc->int_receive = scc_sdlcrx;
  637.     scc->int_special = scc_sdlcsp;
  638.   
  639.     i_state = dirps();
  640.   
  641.     wr(scc,R4,X1CLK|SDLC);          /* *1 clock, SDLC mode */
  642.     wr(scc,R1,z);                   /* no W/REQ operation */
  643.     wr(scc,R3,Rx8|RxCRC_ENAB);      /* RX 8 bits/char, CRC, disabled */
  644.     wr(scc,R5,Tx8|DTR|TxCRC_ENAB);  /* TX 8 bits/char, disabled, DTR */
  645.     wr(scc,R6,z);                   /* SDLC address zero (not used) */
  646.     wr(scc,R7,FLAG);                /* SDLC flag value */
  647.     wr(scc,R9,VIS);                 /* vector includes status */
  648.   
  649.     if (scc->extclock){             /* when using external clocks */
  650.         if (Sccinfo.hwtype & HWBAYCOM){         /* DF9IC-modem? */
  651.             wr(scc,R10,CRCPS|NRZ|ABUNDER);  /* CRC preset 1, select NRZ, ABORT on underrun */
  652.             wr(scc,R11,RCTRxCP|TCRTxCP);    /* RXclk TRxC, TXclk RTxC. */
  653.         } else {
  654.             wr(scc,R10,CRCPS|NRZI|ABUNDER); /* CRC preset 1, select NRZI, ABORT on underrun */
  655.             wr(scc,R11,RCRTxCP|TCTRxCP);    /* RXclk RTxC, TXclk TRxC. */
  656.         }
  657.         wr(scc,R14,z);                          /* No BRG options */
  658.         WRSCC(scc->ctrl,R14,DISDPLL|scc->wreg[R14]); /* No DPLL operation */
  659.     } else {
  660.         wr(scc,R10,CRCPS|NRZI|ABUNDER); /* CRC preset 1, select NRZI, ABORT on underrun */
  661.         if(scc->fulldup){               /* when external clock divider */
  662.             if(Sccinfo.pclk){       /* when using PCLK as clock source */
  663.                 if (Sccinfo.hwtype & HWBAYCOM){
  664.                     /* RXclk DPLL, TXclk RTxC, out=DPLL (Echo duplex) */
  665.                     wr(scc,R11,RCDPLL|TCRTxCP|TRxCOI|TRxCDP);
  666.                 } else {
  667.                     /* RXclk DPLL, TXclk RTxC, out=BRG. external /32 TRxC->RTxC */
  668.                     wr(scc,R11,RCDPLL|TCRTxCP|TRxCOI|TRxCBR);
  669.                 }
  670.             } else {
  671.                 /* RXclk DPLL, TXclk TRxC.      external TX clock to TRxC */
  672.                 wr(scc,R11,RCDPLL|TCTRxCP);
  673.             }
  674.         } else {        /* only half-duplex operation */
  675.             /* RXclk DPLL, TXclk BRG. BRG reprogrammed at every TX/RX switch */
  676. #ifdef notdef   /* KA9Q - for PSK modem */
  677.             wr(scc,R11,RCDPLL|TCBR);
  678. #else
  679.             /* DPLL -> Rx clk, (DPLL -> Tx CLK), DPLL -> TRxC pin */
  680.             wr(scc,R11,RCDPLL|TCDPLL|TRxCOI|TRxCDP);
  681. #endif
  682.         }
  683.         wr(scc,R14,Sccinfo.pclk? BRSRC:z);         /* BRG source = PCLK/RTxC */
  684.         WRSCC(scc->ctrl,R14,SSBR|scc->wreg[R14]);  /* DPLL source = BRG */
  685.         WRSCC(scc->ctrl,R14,SNRZI|scc->wreg[R14]); /* DPLL NRZI mode */
  686.     }
  687.   
  688.     if (Sccinfo.hwtype & HWBAYCOM){         /* BayCom-USCC card? */
  689.         wr(scc,R15,BRKIE|DCDIE);        /* enable ABORT, DCD interrupts */
  690.     } else {
  691.         wr(scc,R15,BRKIE|CTSIE|DCDIE);  /* enable ABORT, CTS & DCD interrupts */
  692.     }
  693.   
  694.     if(RDREG(scc->ctrl) & DCD){             /* DCD is now ON */
  695.         if (!scc->extclock)
  696.             WRSCC(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
  697.         or(scc,R3,ENT_HM|RxENABLE);     /* enable the receiver, hunt mode */
  698.     }
  699.     WRREG(scc->ctrl,RES_EXT_INT);   /* reset ext/status interrupts */
  700.     WRREG(scc->ctrl,RES_EXT_INT);   /* must be done twice */
  701.     scc->status = RDREG(scc->ctrl); /* read initial status */
  702.   
  703.     or(scc,R1,INT_ALL_Rx|TxINT_ENAB|EXT_INT_ENAB); /* enable interrupts */
  704.     or(scc,R9,MIE);                 /* master interrupt enable */
  705.   
  706.     restore(i_state);
  707. }
  708.   
  709. /* set SCC channel speed
  710.  * clkmode specifies the division rate (1,16,32) inside the SCC
  711.  * returns the selected brgrate for "real speed" calculation
  712.  */
  713. static unsigned int
  714. scc_speed(scc,clkmode,speed)
  715. register struct sccchan *scc;
  716. unsigned int clkmode;
  717. long speed;             /* the desired baudrate */
  718. {
  719.     unsigned int brgrate;
  720.     long spdclkm;
  721.     int i_state;
  722.   
  723.     /* calculate baudrate generator value */
  724.   
  725.     if ((spdclkm = speed * clkmode) == 0)
  726.         return 65000U;          /* avoid divide-by-zero */
  727.   
  728.     brgrate = (unsigned) ((Sccinfo.clk + spdclkm) / (spdclkm * 2)) - 2;
  729.   
  730.     i_state = dirps();      /* 2-step register accesses... */
  731.   
  732.     cl(scc,R14,BRENABL);        /* disable baudrate generator */
  733.     wr(scc,R12,brgrate);        /* brg rate LOW */
  734.     wr(scc,R13,brgrate >> 8);       /* brg rate HIGH */
  735.     or(scc,R14,BRENABL);        /* enable baudrate generator */
  736.   
  737.     restore(i_state);
  738.     return brgrate;
  739. }
  740.   
  741. /* de-activate SCC channel */
  742. static int
  743. scc_stop(ifp)
  744. struct iface *ifp;
  745. {
  746.     struct sccchan *scc = Sccchan[ifp->dev];
  747.     int i_state;
  748.   
  749.     i_state = dirps();
  750.   
  751.     VOID(RDREG(scc->ctrl));     /* make sure pointer is written */
  752.     wr(scc,R9,(ifp->dev % 2)? CHRB : CHRA); /* reset the channel */
  753.   
  754.     switch(ifp->type){
  755.         case CL_SERIAL_LINE:
  756.         case CL_KISS:
  757.             free(scc->fifo.buf);
  758.         default:
  759.             break;
  760.     }
  761.     free(scc);
  762.     Sccchan[ifp->dev] = NULLCHAN;
  763.     restore(i_state);
  764.     return 0;
  765. }
  766.   
  767. /* de-activate SCC driver on program exit */
  768. void
  769. sccstop()
  770. {
  771.     if(Sccinfo.init){           /* was it initialized? */
  772.         maskoff(Sccinfo.ivec);      /* disable the interrupt */
  773.         setirq(Sccinfo.ivec,Orgivec);   /* restore original interrupt vector */
  774.     }
  775. }
  776.   
  777. /* perform ioctl on SCC (async) channel
  778.  * this is used for SLIP mode only, and will read/set the line speed
  779.  */
  780. static int32
  781. scc_aioctl(ifp,cmd,set,val)
  782. struct iface *ifp;
  783. int cmd;
  784. int set;
  785. int32 val;
  786. {
  787.     struct sccchan *scc;
  788.     unsigned int brgrate;
  789.   
  790.     scc = Sccchan[ifp->dev];
  791.   
  792.     switch(cmd){
  793.         case PARAM_SPEED:
  794.             if(set){
  795.                 brgrate = scc_speed(scc,16,val);
  796.                 scc->speed = Sccinfo.clk / (32L * (brgrate + 2));
  797.             }
  798.             return scc->speed;
  799.     }
  800.     return 0;
  801. }
  802.   
  803. /* perform ioctl on SCC (sdlc) channel
  804.  * this is used for AX.25 mode only, and will set the "kiss" parameters
  805.  */
  806. static int32
  807. scc_sioctl(ifp,cmd,set,val)
  808. struct iface *ifp;
  809. int cmd;
  810. int set;
  811. int32 val;
  812. {
  813.     struct sccchan *scc;
  814.     int i_state;
  815.     unsigned int brgrate;
  816.   
  817.     scc = Sccchan[ifp->dev];
  818.   
  819.     switch(cmd){
  820.         case PARAM_SPEED:
  821.             if(set){
  822.                 if(val == 0)
  823.                     scc->extclock = 1;
  824.                 else {
  825.                     brgrate = scc_speed(scc,32,val);/* init SCC speed */
  826.                     scc->speed = Sccinfo.clk / (64L * (brgrate + 2));/* calc real speed */
  827.                 }
  828.             }
  829.             return scc->speed;
  830.         case PARAM_TXDELAY:
  831.             if(set)
  832.                 scc->a.txdelay = val;
  833.             return scc->a.txdelay;
  834.         case PARAM_PERSIST:
  835.             if(set)
  836.                 scc->a.persist = val;
  837.             return scc->a.persist;
  838.         case PARAM_SLOTTIME:
  839.             if(set)
  840.                 scc->a.slottime = val;
  841.             return scc->a.slottime;
  842.         case PARAM_TXTAIL:
  843.             if(set)
  844.                 scc->a.tailtime = val;
  845.             return scc->a.tailtime;
  846.         case PARAM_FULLDUP:
  847.             if(set)
  848.                 scc->a.fulldup = val;
  849.             return scc->a.fulldup;
  850.         case PARAM_WAIT:
  851.             if(set)
  852.                 scc->a.waittime = val;
  853.             return scc->a.waittime;
  854.         case PARAM_MAXKEY:
  855.             if(set)
  856.                 scc->a.maxkeyup = val;
  857.             return scc->a.maxkeyup;
  858.         case PARAM_MIN:
  859.             if(set)
  860.                 scc->a.mintime = val;
  861.             return scc->a.mintime;
  862.         case PARAM_IDLE:
  863.             if(set)
  864.                 scc->a.idletime = val;
  865.             return scc->a.idletime;
  866.         case PARAM_DTR:
  867.             if(set){
  868.                 if(val)
  869.                     scc->wreg[R5] |= DTR;
  870.                 else
  871.                     scc->wreg[R5] &= ~DTR;
  872.   
  873.                 i_state = dirps();
  874.                 if(scc->a.tstate == IDLE && scc->timercount == 0)
  875.                     scc->timercount = 1;    /* force an update */
  876.                 restore(i_state);
  877.             }
  878.             return (scc->wreg[R5] & DTR) ? 1 : 0;
  879.         case PARAM_GROUP:
  880.             if(set)
  881.                 scc->group = (int) val;
  882.             return scc->group;
  883.     }
  884.     return -1;
  885. }
  886.   
  887. /* start SCC transmitter when it is idle (SLIP/KISS mode only) */
  888. static void
  889. scc_sstart(scc)
  890. register struct sccchan *scc;
  891. {
  892.     if(scc->tbp != NULLBUF ||   /* busy */
  893.         scc->sndq == NULLBUF)  /* no work */
  894.         return;
  895.   
  896.     scc->tbp = dequeue(&scc->sndq);
  897.     WRREG(scc->data,FR_END);
  898. }
  899.   
  900. /* show SCC status */
  901. int
  902. dosccstat()
  903. {
  904.     register struct sccchan *scc;
  905.     int i;
  906.   
  907.     if(!Sccinfo.init){
  908.         tprintf("SCC driver not initialized\n");
  909.         return 0;
  910.     }
  911.     tprintf("Ch Iface    Sent   Rcvd   Error Space Overr   Rxints   Txints   Exints   Spints\n");
  912.   
  913.     for(i = 0; i <= Sccinfo.maxchan; i++){
  914.         if((scc = Sccchan[i]) == NULLCHAN)
  915.             continue;
  916.   
  917.         if(scc->int_receive == scc_asyrx)
  918.             tprintf("%2d %-6s  ** asynch ** %7lu %5u %5u %8lu %8lu %8lu %8lu\n",i,scc->iface->name,
  919.             scc->rxerrs,scc->nospace,scc->rovers,
  920.             scc->rxints,scc->txints,scc->exints,scc->spints);
  921.         else
  922.             tprintf("%2d %-6s %6lu %6lu %7lu %5u %5u %8lu %8lu %8lu %8lu\n",i,scc->iface->name,
  923.             scc->enqueued,scc->rxframes,scc->rxerrs,scc->nospace,scc->rovers,
  924.             scc->rxints,scc->txints,scc->exints,scc->spints);
  925.     }
  926.     return 0;
  927. }
  928.   
  929. /* send raw frame to SCC. used for AX.25 */
  930. static int
  931. scc_raw(ifp,bp)
  932. struct iface *ifp;
  933. struct mbuf *bp;
  934. {
  935.     struct sccchan *scc;
  936.     int i_state;
  937.   
  938.     dump(ifp,IF_TRACE_OUT,CL_AX25,bp);
  939.     ifp->rawsndcnt++;
  940.     ifp->lastsent = secclock();
  941.   
  942.     scc = Sccchan[ifp->dev];
  943.   
  944.     if (scc->tx_inhibit){       /* transmitter inhibit */
  945.         free_p(bp);
  946.         return -1;
  947.     }
  948.   
  949.     enqueue(&scc->sndq,bp);     /* enqueue packet */
  950.     scc->enqueued++;
  951.   
  952.     i_state = dirps();
  953.   
  954.     if(scc->a.tstate == IDLE){  /* when transmitter is idle */
  955.         scc->a.tstate = DEFER;  /* start the key-up sequence */
  956.         scc->a.maxdefer = TPS * scc->a.idletime /
  957.         scc->a.slottime;
  958.         scc->timercount = scc->a.waittime;
  959.     }
  960.     restore(i_state);
  961.     return 0;
  962. }
  963.   
  964. static int
  965. scc_send(dev,bp)
  966. int dev;
  967. struct mbuf *bp;
  968. {
  969.     struct sccchan *scc;
  970.   
  971.     scc = Sccchan[dev];
  972.     enqueue(&scc->sndq,bp);
  973.   
  974.     if(scc->tbp == NULLBUF)
  975.         scc_sstart(scc);
  976.     return(0);
  977. }
  978.   
  979. /* initialize interface for AX.25 use */
  980. static int
  981. scc_call(ifp,call)
  982. register struct iface *ifp;
  983. char *call;
  984. {
  985.     char out[AXALEN];
  986.   
  987.     ifp->hwaddr = mallocw(AXALEN);
  988.     if(setcall(out,call) == 0)
  989.         memcpy(ifp->hwaddr,out,AXALEN);
  990.     else
  991.         memcpy(ifp->hwaddr,Mycall,AXALEN);
  992.     return 0;
  993. }
  994.   
  995. /* Interrupt handlers for asynchronous modes (kiss, slip) */
  996.   
  997. /* Transmitter interrupt handler */
  998. /* This routine sends data from mbufs in SLIP format */
  999. static void
  1000. scc_asytx(scc)
  1001. register struct sccchan *scc;
  1002. {
  1003.     register struct mbuf *bp;
  1004.   
  1005.     scc->txints++;
  1006.   
  1007.     if(scc->txchar != 0){       /* a character pending for transmit? */
  1008.         WRREG(scc->data,scc->txchar);   /* send it now */
  1009.         scc->txchar = 0;        /* next time, ignore it */
  1010.         return;
  1011.     }
  1012.   
  1013.     if(scc->tbp == NULLBUF){    /* nothing to send? */
  1014.         if((scc->tbp = scc->sndq) != NULLBUF){ /* dequeue next frame */
  1015.             scc->sndq = scc->sndq->anext;
  1016.             WRREG(scc->data,FR_END);    /* send FR_END to flush line garbage */
  1017.         } else {
  1018.             WRREG(scc->ctrl,RES_Tx_P);  /* else only reset pending int */
  1019.         }
  1020.         return;
  1021.     }
  1022.     while ((bp = scc->tbp)->cnt == 0){ /* nothing left in this mbuf? */
  1023.         bp = bp->next;          /* save link to next */
  1024.   
  1025.         free_mbuf(scc->tbp);
  1026.   
  1027.         if((scc->tbp = bp) == NULLBUF){ /* see if more mbufs follow */
  1028.             WRREG(scc->data,FR_END);    /* frame complete, send FR_END */
  1029.             return;
  1030.         }
  1031.     }
  1032.     /* now bp = scc->tbp (either from while or from if stmt above) */
  1033.   
  1034.     WRREG(scc->data,*(bp->data));   /* just send the character */
  1035.     bp->cnt--;              /* decrease mbuf byte count */
  1036.     bp->data++;             /* and increment the data pointer */
  1037. }
  1038.   
  1039. /* External/Status interrupt handler */
  1040. static void
  1041. scc_asyex(scc)
  1042. register struct sccchan *scc;
  1043. {
  1044.     register unsigned char status,changes;
  1045.   
  1046.     scc->exints++;
  1047.     status = RDREG(scc->ctrl);
  1048.     changes = status ^ scc->status;
  1049.   
  1050.     if(changes & BRK_ABRT){     /* BREAK? */
  1051.         if((status & BRK_ABRT) == 0)    /* BREAK now over? */
  1052.             VOID(RDREG(scc->data)); /* read the NUL character */
  1053.     }
  1054.     scc->status = status;
  1055.     WRREG(scc->ctrl,RES_EXT_INT);
  1056. }
  1057.   
  1058. /* Receiver interrupt handler under NOS.
  1059.  * Since the higher serial protocol routines are all written to work
  1060.  * well with the routines in 8250.c, it makes sense to handle
  1061.  * asynch i/o with the 8530 in a similar manner. Therefore, these
  1062.  * routines are as close to their counterparts in 8250.c as possible.
  1063.  */
  1064.   
  1065. static void
  1066. scc_asyrx(scc)
  1067. register struct sccchan *scc;
  1068. {
  1069.     register struct fifo *fp;
  1070.     char c;
  1071.   
  1072.     scc->rxints++;
  1073.   
  1074.     fp = &(scc->fifo);
  1075.     do {
  1076.         c = RDREG(scc->data);
  1077.         if(fp->cnt != fp->bufsize){
  1078.             *fp->wp++ = c;
  1079.             if(fp->wp >= &fp->buf[fp->bufsize])
  1080.                 fp->wp = fp->buf;
  1081.             fp->cnt++;
  1082.         } else
  1083.             scc->nospace++;
  1084.     } while(RDREG(scc->ctrl) & Rx_CH_AV);
  1085.     psignal(fp,1);  /* eventually move this to timer routine */
  1086. }
  1087.   
  1088. /* Blocking read from asynch input.
  1089.  * Essentially the same as get_asy() in 8250.c
  1090.  * See comments in asy_rxint().
  1091.  */
  1092. static int
  1093. get_scc(dev)
  1094. int dev;
  1095. {
  1096.     int i_state;
  1097.     register struct fifo *fp;
  1098.     char c;
  1099.   
  1100.     fp = &(Sccchan[dev]->fifo);
  1101.   
  1102.     i_state = dirps();
  1103.     while(fp->cnt == 0)
  1104.         pwait(fp);
  1105.     fp->cnt--;
  1106.     restore(i_state);
  1107.   
  1108.     c = *fp->rp++;
  1109.     if(fp->rp >= &fp->buf[fp->bufsize])
  1110.         fp->rp = fp->buf;
  1111.   
  1112.     return uchar(c);
  1113. }
  1114.   
  1115. int
  1116. scc_frameup(dev)
  1117. int dev;
  1118. {
  1119.     Sccchan[dev]->rxframes++;
  1120.     return 0;
  1121. }
  1122.   
  1123. /* Receive Special Condition interrupt handler */
  1124. static void
  1125. scc_asysp(scc)
  1126. register struct sccchan *scc;
  1127. {
  1128.     register unsigned char status;
  1129.   
  1130.     scc->spints++;
  1131.   
  1132.     status = rd(scc,R1);        /* read receiver status */
  1133.     VOID(RDREG(scc->data));     /* flush offending character */
  1134.   
  1135.     if(status & (CRC_ERR | Rx_OVR))     /* did a framing error or overrun occur ? */
  1136.         scc->rovers++;          /* report as overrun */
  1137.   
  1138.     WRREG(scc->ctrl,ERR_RES);
  1139. }
  1140.   
  1141. /* Interrupt handlers for sdlc mode (AX.25) */
  1142.   
  1143. /* Transmitter interrupt handler */
  1144. static void
  1145. scc_sdlctx(scc)
  1146. register struct sccchan *scc;
  1147. {
  1148.     register struct mbuf *bp;
  1149.   
  1150.     scc->txints++;
  1151.   
  1152.     switch(scc->a.tstate){      /* look at transmitter state */
  1153.         case ACTIVE:            /* busy sending data bytes */
  1154.             while ((bp = scc->tbp)->cnt == 0){  /* nothing left in this mbuf? */
  1155.                 bp = bp->next;          /* save link to next */
  1156.                 free_mbuf(scc->tbp);    /*KM*/
  1157.                 if((scc->tbp = bp) == NULLBUF){/* see if more mbufs follow */
  1158.                     if(RDREG(scc->ctrl) & TxEOM){   /* check tx underrun status */
  1159.                         scc->rovers++;      /* oops, an underrun! count them */
  1160.                         WRREG(scc->ctrl,SEND_ABORT);/* send an abort to be sure */
  1161.                         scc->a.tstate = TAIL;   /* key down tx after TAILTIME */
  1162.                         scc->timercount = scc->a.tailtime;
  1163.                         return;
  1164.                     }
  1165.                     cl(scc,R10,ABUNDER);        /* frame complete, allow CRC transmit */
  1166.                     scc->a.tstate = FLUSH;
  1167.                     WRREG(scc->ctrl,RES_Tx_P);  /* reset pending int */
  1168.                     return;
  1169.                 }
  1170.             }
  1171.         /* now bp = scc->tbp (either from while or from if stmt above) */
  1172.             WRREG(scc->data,*(bp->data++)); /* send the character */
  1173.             bp->cnt--;          /* decrease mbuf byte count */
  1174.             return;
  1175.         case FLUSH: /* CRC just went out, more to send? */
  1176.             or(scc,R10,ABUNDER);        /* re-install underrun protection */
  1177.         /* verify that we are not exeeding max tx time (if defined) */
  1178.             if((scc->timercount != 0 || scc->a.maxkeyup == 0) &&
  1179.             (scc->tbp = scc->sndq) != NULLBUF){ /* dequeue a frame */
  1180.                 scc->sndq = scc->sndq->anext;
  1181.                 WRREG(scc->ctrl,RES_Tx_CRC); /* reset the TX CRC generator */
  1182.                 scc->a.tstate = ACTIVE;
  1183.                 scc_sdlctx(scc);        /* write 1st byte */
  1184.                 WRREG(scc->ctrl,RES_EOM_L); /* reset the EOM latch */
  1185.                 return;
  1186.             }
  1187.             scc->a.tstate = TAIL;       /* no more, key down tx after TAILTIME */
  1188.             scc->timercount = scc->a.tailtime;
  1189.             WRREG(scc->ctrl,RES_Tx_P);
  1190.             return;
  1191.         default:                /* another state */
  1192.             WRREG(scc->ctrl,RES_Tx_P);  /* then don't send anything */
  1193.             return;
  1194.     }
  1195. }
  1196.   
  1197. /* External/Status interrupt handler */
  1198. static void
  1199. scc_sdlcex(scc)
  1200. register struct sccchan *scc;
  1201. {
  1202.     register unsigned char status,changes;
  1203.   
  1204.     scc->exints++;
  1205.     status = RDREG(scc->ctrl);
  1206.     changes = status ^ scc->status;
  1207.   
  1208.     if(changes & BRK_ABRT){     /* Received an ABORT */
  1209.         if(status & BRK_ABRT){      /* is this the beginning? */
  1210.             if(scc->rbp != NULLBUF){/* did we receive something? */
  1211.                 /* check if a significant amount of data came in */
  1212.                 /* this is because the drop of DCD tends to generate an ABORT */
  1213.                 if(scc->rbp->next != NULLBUF || scc->rbp->cnt > sizeof(struct phdr))
  1214.                     scc->rxerrs++;  /* then count it as an error */
  1215.                 scc_tossb(scc);     /* throw away buffer */
  1216.             }
  1217.             VOID(RDREG(scc->data)); /* flush the FIFO */
  1218.             VOID(RDREG(scc->data));
  1219.             VOID(RDREG(scc->data));
  1220.         }
  1221.     }
  1222.     if(changes & CTS){          /* CTS input changed state */
  1223.         if(status & CTS){       /* CTS is now ON */
  1224.             if(scc->a.tstate == KEYWT &&
  1225.                 scc->a.txdelay == 0) /* zero TXDELAY = wait for CTS */
  1226.                 scc->timercount = 1;    /* it will start within 10 ms */
  1227.         }
  1228.     }
  1229.     if(changes & DCD){          /* DCD input changed state */
  1230.         if(status & DCD){       /* DCD is now ON */
  1231.             if (!scc->extclock)
  1232.                 WRSCC(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
  1233.             or(scc,R3,ENT_HM|RxENABLE); /* enable the receiver, hunt mode */
  1234.         } else {            /* DCD is now OFF */
  1235.             cl(scc,R3,ENT_HM|RxENABLE); /* disable the receiver */
  1236.             VOID(RDREG(scc->data)); /* flush the FIFO */
  1237.             VOID(RDREG(scc->data));
  1238.             VOID(RDREG(scc->data));
  1239.             if(scc->rbp != NULLBUF){/* did we receive something? */
  1240.                 /* check if a significant amount of data came in */
  1241.                 /* this is because some characters precede the drop of DCD */
  1242.                 if(scc->rbp->next != NULLBUF || scc->rbp->cnt > sizeof(struct phdr))
  1243.                     scc->rxerrs++;  /* then count it as an error */
  1244.                 scc_tossb(scc);     /* throw away buffer */
  1245.             }
  1246.         }
  1247.     }
  1248.     scc->status = status;
  1249.     WRREG(scc->ctrl,RES_EXT_INT);
  1250. }
  1251.   
  1252. /* Receiver interrupt handler */
  1253. static void
  1254. scc_sdlcrx(scc)
  1255. register struct sccchan *scc;
  1256. {
  1257.     register struct mbuf *bp;
  1258.   
  1259.     scc->rxints++;
  1260.   
  1261.     if((bp = scc->rbp1) == NULLBUF){ /* no buffer available now */
  1262.         if(scc->rbp == NULLBUF){
  1263.             if((bp = alloc_mbuf(scc->bufsiz+sizeof(struct phdr))) != NULLBUF){
  1264.                 scc->rbp = scc->rbp1 = bp;
  1265.                 bp->cnt = sizeof(struct phdr);  /* get past the header */
  1266.             }
  1267.         } else if((bp = alloc_mbuf(scc->bufsiz)) != NULLBUF){
  1268.             scc->rbp1 = bp;
  1269.             for(bp = scc->rbp; bp->next != NULLBUF; bp = bp->next);
  1270.             bp->next = scc->rbp1;
  1271.             bp = scc->rbp1;
  1272.         }
  1273.         if(bp == NULLBUF){
  1274.             VOID(RDREG(scc->data)); /* so we have to discard the char */
  1275.             or(scc,R3,ENT_HM);      /* enter hunt mode for next flag */
  1276.             scc_tossb(scc);     /* put buffers back on pool */
  1277.             scc->nospace++;     /* count these events */
  1278.             return;
  1279.         }
  1280.     }
  1281.   
  1282.     /* now, we have a buffer (at bp). read character and store it */
  1283.     bp->data[bp->cnt++] = RDREG(scc->data);
  1284.   
  1285.     if(bp->cnt == bp->size)     /* buffer full? */
  1286.         scc->rbp1 = NULLBUF;    /* acquire a new one next time */
  1287. }
  1288.   
  1289. /* Receive Special Condition interrupt handler */
  1290. static void
  1291. scc_sdlcsp(scc)
  1292. register struct sccchan *scc;
  1293. {
  1294.     register unsigned char status;
  1295.     register struct mbuf *bp;
  1296.     struct phdr phdr;
  1297.   
  1298.     scc->spints++;
  1299.   
  1300.     status = rd(scc,R1);        /* read receiver status */
  1301.     VOID(RDREG(scc->data));     /* flush offending character */
  1302.   
  1303.     if(status & Rx_OVR){        /* receiver overrun */
  1304.         scc->rovers++;          /* count them */
  1305.         or(scc,R3,ENT_HM);      /* enter hunt mode for next flag */
  1306.         scc_tossb(scc);         /* rewind the buffer and toss */
  1307.     }
  1308.     if(status & END_FR &&       /* end of frame */
  1309.     scc->rbp != NULLBUF){   /* at least received something */
  1310.         if((status & CRC_ERR) == 0 &&   /* no CRC error is indicated */
  1311.             (status & 0xe) == RES8 &&   /* 8 bits in last byte */
  1312.         scc->rbp->cnt > sizeof(phdr)){
  1313.   
  1314.             /* we seem to have a good frame. but the last byte received */
  1315.             /* from rx interrupt is in fact a CRC byte, so discard it */
  1316.             if(scc->rbp1 != NULLBUF){
  1317.                 scc->rbp1->cnt--;   /* current mbuf was not full */
  1318.             } else {
  1319.                 for(bp = scc->rbp; bp->next != NULLBUF; bp = bp->next);
  1320.                     /* find last mbuf */
  1321.   
  1322.                 bp->cnt--;      /* last byte is first CRC byte */
  1323.             }
  1324.   
  1325.             phdr.iface = scc->iface;
  1326.             phdr.type = CL_AX25;
  1327.             memcpy(&scc->rbp->data[0],(char *)&phdr,sizeof(phdr));
  1328.             enqueue(&Hopper,scc->rbp);
  1329.   
  1330.             scc->rbp = scc->rbp1 = NULLBUF;
  1331.             scc->rxframes++;
  1332.         } else {            /* a bad frame */
  1333.             scc_tossb(scc);     /* throw away frame */
  1334.             scc->rxerrs++;
  1335.         }
  1336.     }
  1337.     WRREG(scc->ctrl,ERR_RES);
  1338. }
  1339.   
  1340. /* Throw away receive mbuf(s) when an error occurred */
  1341. static void
  1342. scc_tossb (scc)
  1343. register struct sccchan *scc;
  1344. {
  1345.     register struct mbuf *bp;
  1346.   
  1347.     if((bp = scc->rbp) != NULLBUF){
  1348.         free_p(bp->next);
  1349.         free_p(bp->dup);    /* Should be NULLBUF */
  1350.         bp->next = NULLBUF;
  1351.         scc->rbp1 = bp;     /* Don't throw this one away */
  1352.         bp->cnt = sizeof(struct phdr);  /* Simply rewind it */
  1353.     }
  1354. }
  1355.   
  1356. /* Switch the SCC to "transmit" mode */
  1357. /* Only to be called from an interrupt handler, while in AX.25 mode */
  1358. static void
  1359. scc_txon(scc)
  1360. register struct sccchan *scc;
  1361. {
  1362.     if (!scc->fulldup && !scc->extclock){ /* no fulldup divider? */
  1363.         cl(scc,R3,RxENABLE);        /* then switch off receiver */
  1364.         cl(scc,R5,TxENAB);      /* transmitter off during switch */
  1365.         scc_speed(scc,1,scc->speed);    /* reprogram baudrate generator */
  1366.         if(Sccinfo.hwtype & HWBAYCOM){
  1367.             /* DPLL -> Rx clk, BRG -> Tx CLK, TxCLK -> TRxC pin */
  1368.             wr(scc,R11,RCDPLL|TCBR|TRxCOI|TRxCBR);
  1369.         }
  1370.     }
  1371.     or(scc,R5,RTS|TxENAB);      /* set the RTS line and enable TX */
  1372.     if(Sccinfo.hwtype & HWPRIMUS)   /* PRIMUS has another PTT bit... */
  1373.         WRREG(scc->ctrl + 4,Sccinfo.hwparam | 0x80); /* set that bit! */
  1374. }
  1375.   
  1376. /* Switch the SCC to "receive" mode (or: switch off transmitter)
  1377.  * Only to be called from an interrupt handler, while in AX.25 mode
  1378.  */
  1379. static void
  1380. scc_txoff(scc)
  1381. register struct sccchan *scc;
  1382. {
  1383.     cl(scc,R5,RTS);         /* turn off RTS line */
  1384.     if(Sccinfo.hwtype & HWPRIMUS)   /* PRIMUS has another PTT bit... */
  1385.         WRREG(scc->ctrl + 4,Sccinfo.hwparam); /* clear that bit! */
  1386.   
  1387.     if (!scc->fulldup && !scc->extclock){ /* no fulldup divider? */
  1388.         cl(scc,R5,TxENAB);      /* then disable the transmitter */
  1389.         scc_speed(scc,32,scc->speed);   /* back to receiver baudrate */
  1390.         if(Sccinfo.hwtype & HWBAYCOM){
  1391.             /* DPLL -> Rx clk, DPLL -> Tx CLK, RxCLK -> TRxC pin */
  1392.             wr(scc,R11,RCDPLL|TCDPLL|TRxCOI|TRxCDP);
  1393.             or(scc,R3,ENT_HM|RxENABLE);     /* enable the receiver, hunt mode */
  1394.         }
  1395.     }
  1396. }
  1397.   
  1398. /* SCC timer interrupt handler. Will be called every 1/TPS s by the
  1399.  * routine systick in pc.c
  1400.  */
  1401. void scctimer()
  1402. {
  1403.     register struct sccchan *scc;
  1404.     register struct sccchan **sccp;
  1405.     int i_state;
  1406.   
  1407.     i_state = dirps();
  1408.     for(sccp = Sccchan + Sccinfo.maxchan; sccp >= Sccchan; sccp--){
  1409.         if((scc = *sccp) != NULLCHAN &&
  1410.             scc->timercount != 0 &&
  1411.         --(scc->timercount) == 0){
  1412.             /* handle an SCC timer event for this SCC channel
  1413.              * this can only happen when the channel is AX.25 type
  1414.              * (the SLIP/KISS driver does not use timers)
  1415.              */
  1416.             switch(scc->a.tstate){
  1417.                 case IDLE:          /* it was idle, this is FULLDUP2 timeout */
  1418.                     scc_txoff(scc);     /* switch-off the transmitter */
  1419.                     break;
  1420.                 case DEFER:         /* trying to get the channel */
  1421.                 /* operation is as follows:
  1422.                  * CSMA: when channel clear AND persistence randomgenerator
  1423.                  *   wins, AND group restrictions allow it:
  1424.                  *      keyup the transmitter
  1425.                  *   if not, delay one SLOTTIME and try again
  1426.                  * FULL: always keyup the transmitter
  1427.                  */
  1428.                     if(scc->a.fulldup == 0){
  1429.                         Random = 21 * Random + 53;
  1430.                         if(scc->status & DCD || scc->a.persist < Random){
  1431.                         /* defer transmission again. check for limit */
  1432.                             defer_it:                   if(--(scc->a.maxdefer) == 0){
  1433.                             /* deferred too long. choice is to:
  1434.                              * - throw away pending frames, or
  1435.                              * - smash-on the transmitter and send them.
  1436.                              * the first would be the choice in a clean
  1437.                              * environment, but in the amateur radio world
  1438.                              * a distant faulty station could tie us up
  1439.                              * forever, so the second may be better...
  1440.                             */
  1441. #ifdef THROW_AWAY_AFTER_DEFER_TIMEOUT
  1442.                                 struct mbuf *bp,*bp1;
  1443.   
  1444.                                 while ((bp = scc->sndq) != NULLBUF){
  1445.                                     scc->sndq = scc->sndq->anext;
  1446.                                     free_p(bp);
  1447.                                 }
  1448. #else
  1449.                                 goto keyup; /* just keyup the transmitter... */
  1450. #endif
  1451.                             }
  1452.                             scc->timercount = scc->a.slottime;
  1453.                             break;
  1454.                         }
  1455.                         if(uchar(scc->group) != NOGROUP){
  1456.                             int i;
  1457.                             struct sccchan *scc2;
  1458.   
  1459.                             for(i = 0; i <= Sccinfo.maxchan; i++)
  1460.                                 if((scc2 = Sccchan[i]) != NULLCHAN &&
  1461.                                     scc2 != scc &&
  1462.                                     uchar(scc2->group) & uchar(scc->group) &&
  1463.                                     ((scc->group & TXGROUP && scc2->wreg[R5] & RTS) ||
  1464.                                 (scc->group & RXGROUP && scc2->status & DCD))){
  1465.                                     goto defer_it;
  1466.                                 }
  1467.                         }
  1468.                     }
  1469.                 case KEYUP:         /* keyup transmitter (note fallthrough) */
  1470.                     keyup:              if((scc->wreg[R5] & RTS) == 0){ /* when not yet keyed */
  1471.                         scc->a.tstate = KEYWT;
  1472.                         scc->timercount = scc->a.txdelay; /* 0 if CTSwait */
  1473.                         scc_txon(scc);
  1474.                         break;
  1475.                     }
  1476.                 /* when already keyed, directly fall through */
  1477.                 case KEYWT:         /* waited for CTS or TXDELAY */
  1478.                 /* when a frame is available (it should be...):
  1479.                  * - dequeue it from the send queue
  1480.                  * - reset the transmitter CRC generator
  1481.                  * - set a timeout on transmission length, if defined
  1482.                  * - send the first byte of the frame
  1483.                  * - reset the EOM latch
  1484.                  * when no frame available, proceed to TAIL handling
  1485.                  */
  1486.                     if((scc->tbp = scc->sndq) != NULLBUF){
  1487.                         scc->sndq = scc->sndq->anext;
  1488.                         WRREG(scc->ctrl,RES_Tx_CRC);
  1489.                         scc->a.tstate = ACTIVE;
  1490.                         scc->timercount = TPS * scc->a.maxkeyup;
  1491.                         scc_sdlctx(scc);
  1492.                         WRREG(scc->ctrl,RES_EOM_L);
  1493.                         break;
  1494.                     }
  1495.                 /* when no frame queued, fall through to TAIL case */
  1496.                 case TAIL:          /* at end of frame */
  1497.                 /* when fulldup is 0 or 1, switch off the transmitter.
  1498.                  * when frames are still queued (because of transmit time limit),
  1499.                  * restart the procedure to get the channel after MINTIME.
  1500.                  * when fulldup is 2, the transmitter remains keyed and we
  1501.                  * continue sending.    IDLETIME is an idle timeout in this case.
  1502.                  */
  1503.                     if(scc->a.fulldup < 2){
  1504.                         scc->a.tstate = IDLE;
  1505.                         scc_txoff(scc);
  1506.   
  1507.                         if(scc->sndq != NULLBUF){
  1508.                             scc->a.tstate = DEFER;
  1509.                             scc->a.maxdefer = TPS * scc->a.idletime /
  1510.                             scc->a.slottime;
  1511.                             scc->timercount = TPS * scc->a.mintime;
  1512.                         }
  1513.                         break;
  1514.                     }
  1515.                     if(scc->sndq != NULLBUF){ /* still frames on the queue? */
  1516.                         scc->a.tstate = KEYWT; /* continue sending */
  1517.                         scc->timercount = TPS * scc->a.mintime; /* after mintime */
  1518.                     } else {
  1519.                         scc->a.tstate = IDLE;
  1520.                         scc->timercount = TPS * scc->a.idletime;
  1521.                     }
  1522.                     break;
  1523.                 case ACTIVE:    /* max keyup time expired */
  1524.                 case FLUSH: /* same while in flush mode */
  1525.                     break;  /* no action required yet */
  1526.                 default:            /* unexpected state */
  1527.                     scc->a.tstate = IDLE; /* that should not happen, but... */
  1528.                     scc_txoff(scc);     /* at least stop the transmitter */
  1529.                     break;
  1530.             }
  1531.         }
  1532.     }
  1533.     restore(i_state);
  1534. }
  1535. #endif /* SCC */
  1536.   
  1537.